#!/usr/bin/env python
# encoding: utf-8

"""This is the public interface to use one of the storage backends, as
set in the configuration.
"""

import sys
import logging
from importlib import import_module

from spyro.config.register import Register
from spyro.internal.utils.exceptions import SessionException

log = logging.getLogger(__name__)

Storage = None

class Session:
    """The spyro session manager supports several backends, and it is really
    simple to develop a new one.
    """

    def __init__(self):
        """This method uses python introspection to get access to the
        caller variables to work with, without the need to pass it as
        parameter.

        Note: we load the storage only once, then we store it in a global
        variable.

        We do not handle any exception because, on failure, it must raise
        a 500 page with that error.
        """

        global Storage

        if Storage is None:
            name = Register.sessions['storage']
            
            log.debug("Using the session storage %(name)r." % locals())
            
            Storage = import_module('spyro.session.storage.%s' % name)
            try:
                Storage = getattr(Storage, 'Storage')
            except AttributeError:
                raise AttributeError('Could not find the "Storage" class for '
                                     'the backend %r' % name)

        # getting the caller's request and response object
        request = sys._getframe(1).f_locals['self'].request
        response = sys._getframe(1).f_locals['self'].response

        self._storage = Storage(request, response)

    def __setitem__(self, key, value):
        """Refer to the storage backend to get more informations.
        In the previous version of this interface it was called "put"
        """

        return self._storage.__setitem__(key, value)

    def __getitem__(self, key):
        """Refer to the storage backend to get more informations.
        In the previous version of this interface it was called "get"
        """

        return self._storage.__getitem__(key)

    def get(self, key, default=str()):
        """Refer to the storage backend to get more informations.
        It works like the previous "get", and also like the dict.get()
        accepting an argument to return if nothing has been returned.
        Relies on self.__getitem__
        """

        try:
            return self._storage.__getitem__(key)
        except SessionException:
            return default

    def __delitem__(self, key):
        """Refer to the storage backend to get more informations
        """

        return self._storage.__delitem__(key)

    def destroy(self):
        """Refer to the storage backend to get more informations.
        """

        return self._storage.destroy()
    
    def __contains__(self, key):
        """Refer to the storage backend to get more informations.
        """
        
        return self._storage.__contains__(key)
